package GtEngine

import (
	"net"
	. "tksLog"
	. "tksStatic"
	. "tksTcp"
)

type clientCallback func(net.Conn, uint32, uint32, []byte)

var server *TksTcpConn
var clientCmds map[uint32]clientCallback

func init() {
	clientCmds = make(map[uint32]clientCallback)
}

func clientInit(conn net.Conn) {
	Debug("new connnect from %s", conn.RemoteAddr().String())
}

func clientReceive(conn net.Conn, cmd uint32, from uint32, to uint32, data []byte) {
	// Debug("Receive data from %s, cmd: %d, data: %s", conn.RemoteAddr().String(), cmd, string(data))
	if to == 0 {
		//发送给自己的消息.
		if cb, ok := clientCmds[cmd]; ok {
			cb(conn, from, to, data)
		}
	} else {
		//需要转发消息.
		server := FindServerById(from)
		if server == nil {
			//from client to sevrer
			//find client
			client := FindGateClientByAddr(conn.RemoteAddr().String())
			if client == nil {
				//client not register
				conn.Close()
				return
			}
			//find target server
			server = FindServerByCmd(cmd)
			if server == nil {
				server = FindServerById(client.ServerID)
			}
			if server == nil {
				//no this server
				conn.Close()
				return
			}
			SendBuffer(server.Conn, cmd, client.Id, 0, data)
		} else {
			//from server to client
			if server.Conn.RemoteAddr().String() != conn.RemoteAddr().String() {
				//error server
				conn.Close()
				return
			}
			//find client
			client := FindGateClientById(to)
			if client == nil {
				//client not register
				return
			}
			SendBuffer(client.Conn, cmd, 0, 0, data)
		}
	}

}

func clientClose(conn net.Conn) {
	Debug("client close connect from %s\n", conn.RemoteAddr().String())
}

func RegisterGateCmd(cmd uint32, cb clientCallback) {
	_, ok := clientCmds[cmd]
	if ok {
		return
	} else {
		clientCmds[cmd] = cb
	}
}

func NewGate(port string) error {
	server = new(TksTcpConn)
	Debug("new gate: %s", port)
	err := server.CreateServer(port, clientInit, clientReceive, clientClose)
	if err != nil {
		return err
	}
	return nil
}

func ServerHeartbeat(conn net.Conn, from uint32, to uint32, buf []byte) {
	Debug("recv heartbeat from %s %d", conn.RemoteAddr().String(), from)
	server := FindServerByAddr(conn.RemoteAddr().String())
	if server != nil {
		server.Toc <- 0
		//
		sendRsp(conn, CmdGateHeartbeatRsp, 0, 0, RetSucc)
		return
	}
	client := FindGateClientByAddr(conn.RemoteAddr().String())
	if client != nil {
		client.Toc <- 0
		//
		sendRsp(conn, CmdGateHeartbeatRsp, 0, 0, RetSucc)
		return
	}
	conn.Close()
}
